package com.tanhua.server.service;

import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.FollowUser;
import com.tanhua.domain.mongo.Video;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.VideoVo;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.FollowUserApi;
import com.tanhua.dubbo.api.mongo.VideoApi;
import com.tanhua.server.interceptors.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class VideoService {

    @Reference
    private VideoApi videoApi;

    @Reference
    private UserInfoApi userInfoApi;

    @Reference
    private FollowUserApi followUserApi;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private FastFileStorageClient fastdfs;

    @Autowired
    private FdfsWebServer fdfsWebServer;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 上传小视频
     * @param videoThumbnail
     * @param videoFile
     */
    @CacheEvict(value = "videoList", allEntries = true)
    public void add(MultipartFile videoThumbnail, MultipartFile videoFile) {
        //1. 封面上传到oss
        try {
            String picUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
            //2. 视频文件上传fastdfs
            // 目标：视频文件的后缀名
            // 获取上传文件的源文件名videoFile.getOriginalFilename();  aaa.xxx.jpg  后缀名=jpg
            String videoFilename = videoFile.getOriginalFilename();
            // substring 截取字符串, p1: 从哪里开始。从1开始
            // videoFilename.lastIndexOf(".") lastIndexOf 最后的Index下标of谁的 从最后的哪个下标开始
            String suffix = videoFilename.substring(videoFilename.lastIndexOf(".") + 1);//+1的原因 只要后缀名，不要点
            // 调用fastdfs, 第三个参数是文件的后缀名
            StorePath storePath = fastdfs.uploadFile(videoFile.getInputStream(), videoFile.getSize(), suffix, null);
            // 视频的完整路径
            String videoUrl = fdfsWebServer.getWebServerUrl()+storePath.getFullPath();
            //3. 构建pojo
            Video pojo = new Video();
            pojo.setVideoUrl(videoUrl);
            pojo.setPicUrl(picUrl);
            pojo.setUserId(UserHolder.getUserId());
            pojo.setText("黑马出品");
            //4. 调用api保存视频信息
            videoApi.add(pojo);
        } catch (IOException e) {
            //e.printStackTrace();
            log.error("上传视频失败", e);
            throw new TanHuaException("上传视频失败");
        }
    }

    /**
     * 小视频分页列表
     * @param page
     * @param pageSize
     * @return
     *
     * key: videoList::1_10
     */
    @Cacheable(value = "videoList", key = "#page + '_' + #pageSize" )
    public PageResult findPage(Long page, Long pageSize) {
        //1. 调用api分页查询小视频
        PageResult pageResult = videoApi.findPage(page,pageSize);
        //2. 获取作者id,
        //2.1 获取分页的结果集
        List<Video> videoList = (List<Video>) pageResult.getItems();
        List<VideoVo> voList = new ArrayList<>();
        //2.2 非空判断
        if(!CollectionUtils.isEmpty(videoList)) {
            //2.3 获取所有作者的id
            List<Long> userIds = videoList.stream().map(Video::getUserId).collect(Collectors.toList());
            //2.4 批量查询作者信息
            List<UserInfo> userInfoList = userInfoApi.findByBatchId(userIds);
            // 转成map
            Map<Long, UserInfo> userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserInfo::getId, u -> u));
            //3. 转成vo
            //3.1 以小视频的结果集来遍历，构建pojo, 添加到voList
            for (Video video : videoList) {
                VideoVo vo = new VideoVo();
                // 视频信息复制
                BeanUtils.copyProperties(video,vo);
                vo.setSignature(video.getText());
                vo.setCover(video.getPicUrl());
                //【注意】不要漏，点赞与评论就会出问题
                vo.setId(video.getId().toHexString());
                // 作者信息
                UserInfo userInfo = userInfoMap.get(video.getUserId());
                BeanUtils.copyProperties(userInfo,vo);

                // 登录用户是否关注了作者
                String key = "Follow_User_" + UserHolder.getUserId() + "_" + video.getUserId();
                if (stringRedisTemplate.hasKey(key)) {
                    // 关注过了
                    vo.setHasFocus(1);
                }
                voList.add(vo);
            }
        }
        //3.2 将voList设置到pageResult
        pageResult.setItems(voList);
        //4. 返回pageResult
        return pageResult;
    }

    /**
     * 关注小视频的作者
     * @param authorId
     */
    @CacheEvict(value = "videoList", allEntries = true)
    public void followUser(Long authorId) {
        //1. 构建pojo
        FollowUser followUser = new FollowUser();
        followUser.setUserId(UserHolder.getUserId());
        followUser.setFollowUserId(authorId);
        //2. 调用api保存数据
        followUserApi.add(followUser);
        //3. 标记redis当前登录用户关注了这个作者
        String key = "Follow_User_" + UserHolder.getUserId() + "_" + authorId;
        stringRedisTemplate.opsForValue().set(key, "1");
    }

    /**
     * 取消小视频的作者关注
     * @param authorId
     */
    @CacheEvict(value = "videoList", allEntries = true)
    public void unfollowUser(Long authorId) {
        //1. 构建pojo
        FollowUser followUser = new FollowUser();
        followUser.setUserId(UserHolder.getUserId());
        followUser.setFollowUserId(authorId);
        //2. 调用api删除
        followUserApi.remove(followUser);
        //3. 删除标记redis
        String key = "Follow_User_" + UserHolder.getUserId() + "_" + authorId;
        stringRedisTemplate.delete(key);
    }
}
